#ifndef svl_TValue_H
#define svl_TValue_H

#include "svl.h"

namespace svl {

///////////////////////////////////////////////////////////////////////////////

struct TValue : virtual public TPointer
{
  enum EType
  {
    EType_Unknown,
    EType_Integer,
    EType_Double,
    EType_String,
    EType_Object
  };
  TValue() { isNull = true;}
  //
  virtual bool  IsNull() { return isNull;}
  virtual void SetNull(bool V = true) { isNull = V;}
  void CopyIsNullFrom(TValue *From) { isNull = From->isNull;}
  //
  virtual TString GetValueAsString() { Except("GetValueAsString"); return TString();}
  //
  virtual void SetValueInteger(int V)    { Except("SetValueInteger");}
  virtual void SetValueDouble(double V)  { Except("SetValueDouble");}
  virtual void SetValueString(TString V) { Except("SetValueString");}
  //
  virtual int     GetValueInteger()  { Except("GetValueInteger"); return 0;}
  virtual double  GetValueDouble()   { Except("GetValueDouble");  return 0;}
  virtual TString GetValueString()   { Except("GetValueString");  return TString();}
  //
  virtual EType   GetType() { return EType_Unknown;}
  virtual TString GetInfo() { return TString(); }
  //
  virtual TValue *New()               { Except("New"); return NULL;}
  virtual void CopyFrom(TValue *From) { Except("CopyFrom");}
  
protected:
  bool isNull;
  svl_Except;
};

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

struct TValueInteger : public TValue
{
  void SetValue(int V) { isNull = false; value = V;}
  int  GetValue()      { if (isNull) { Except("GetValue[isNull]");} return value;}
  //
  virtual void SetValueInteger(int V) { SetValue(V);}
  virtual int  GetValueInteger()      { return GetValue();}
  //
  virtual TString GetValueAsString() { return IsNull() ? TString() : value;}
  //
  virtual EType   GetType() { return EType_Integer;}
  virtual TString GetInfo();
  virtual TInfoParam AddInfoTo(TInfoParam Info);
  //
  virtual TValue *New()               { return new TValueInteger;}
  virtual void CopyFrom(TValue *From) { CopyIsNullFrom(From); value = dynamic_cast<TValueInteger*>(From)->value;}

private:
  int value;
  svl_Except;
};

///////////////////////////////////////////////////////////////////////////////

struct TValueDouble : public TValue
{
  void   SetValue(double V) { isNull = false; value = V;}
  double GetValue()         { if (isNull) { Except("GetValue[isNull]");} return value;}
  //
  virtual void   SetValueDouble(double V) { SetValue(V);}
  virtual double GetValueDouble()         { return GetValue();}
  //
  virtual TString GetValueAsString() { return IsNull() ? TString() : value;}
  //
  virtual EType   GetType() { return EType_Double;}
  virtual TString GetInfo();
  virtual TInfoParam AddInfoTo(TInfoParam Info);
  //
  virtual TValue *New()               { return new TValueDouble;}
  virtual void CopyFrom(TValue *From) { CopyIsNullFrom(From); value = dynamic_cast<TValueDouble*>(From)->value;}

private:
  double value;
  svl_Except;
};

///////////////////////////////////////////////////////////////////////////////

struct TValueString : public TValue
{
  TValueString()          {}
  TValueString(TString V) { SetValue(V);}
  //
  void operator = (TString V) { SetValue(V); }
  //
  void    SetValue(TString V) { isNull = false; value = V;}
  TString GetValue()          { if (isNull) { Except("GetValue[isNull]");} return value;}
  //
  virtual void    SetValueString(TString V) { SetValue(V);}
  virtual TString GetValueString()          { return GetValue();}
  //
  virtual TString GetValueAsString() { return IsNull() ? TString() : value;}
  //
  virtual EType   GetType() { return EType_String;}
  virtual TString GetInfo();
  virtual TInfoParam AddInfoTo(TInfoParam Info);
  //
  virtual TValue *New()               { return new TValueString;}
  virtual void CopyFrom(TValue *From) { CopyIsNullFrom(From); value = dynamic_cast<TValueString*>(From)->value;}

private:
  TString value;
  svl_Except;
};

// Object /////////////////////////////////////////////////////////////////////

struct TValueObjectBase : public TValue
{
  //virtual TPointer *GetValueAsPointer()=0;
  //virtual void SetValueAsPointer(TPointer *P)=0;
  
protected:  
  TValueObjectBase() {}
};

template<typename VT>struct TValueObject : public TValueObjectBase
{
  TValueObject() { isNull = false;}
  //
  //void SetValue(VT &V) { isNull = false; value = V;}
  VT  &GetValue()      { if (isNull) { Except("GetValue[isNull]");} return value;}
  //
  virtual TString GetValueAsString() { return IsNull() ? TString() : TString() << &value;}
  //
  virtual EType   GetType() { return EType_Object;}
/************
  virtual TString GetInfo()
  { 
    TString S; if (isNull) {
      S = "NULL";
    }
    else { 
      S << &value;
    }
    return S << " [" << svl_ClassName(*this) << "]";
  }
****************/  
  virtual TInfoParam AddInfoTo(TInfoParam Info) { return TValue::AddInfoTo(Info).Add("value",value);}
  //
  virtual TValue *New()               { return new TValueObject;}
  virtual void CopyFrom(TValue *From) { CopyIsNullFrom(From); value = dynamic_cast<TValueObject*>(From)->value;}
  //
  void operator = (TValueObject &From) { CopyFrom(&From);}

private:
  VT value;
  svl_Except;
};

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

struct TValueVariant : virtual public TPointer
{
  TValueVariant() { value = NULL;}
  TValueVariant(TValueVariant &V) { value = NULL; *this = V;}
 ~TValueVariant() { delete value;}
  //
  bool IsNull() { return value ? value->IsNull() : true;}
  //
  void    SetValue(TValue *V) { delete value; value = V;}
  TValue *GetValue() { return value;}
  //
  void CopyFrom(TValueVariant &V);
  //TValueVariant GetValue() { return value ? TValueVariant(*value) : TValueVariant();}
  void operator = (TValueVariant &V) { CopyFrom(V);}
  //
  void SetValueInteger(int V);
  void SetValueDouble(double V);
  void SetValueString(TString V);
  //
  int     GetValueInteger();
  double  GetValueDouble();
  TString GetValueString();
  //
  TString GetValueAsString() { return value ? value->GetValueAsString() : TString();}
  //
  virtual TInfoParam AddInfoTo(TInfoParam Info);
 
private:
  TValue *value;
  svl_Except;
};

///////////////////////////////////////////////////////////////////////////////
}

#endif
